import json
import copy
from django.db import models
from django.db.models.fields import DateField, DateTimeField
from django.db.models.fields.related import ManyToManyField


class BaseModel(models.Model):
    class Meta:
        abstract = True

    # 返回self._meta.fields中没有的，但是又是需要的字段名的列表
    # 形如['name','type']
    def getMtMField(self):
        pass

    # 返回需要在json中忽略的字段名的列表
    # 形如['password']
    def getIgnoreList(self):
        pass

    def isAttrInstance(self, attr, clazz):
        return isinstance(getattr(self, attr), clazz)

    def toDict(self, fields=None, exclude=None):
        data = {}
        for f in self._meta.concrete_fields + self._meta.many_to_many:
            value = f.value_from_object(self)
            if fields and f.name not in fields:
                continue
            if exclude and f.name in exclude:
                continue
            if isinstance(f, ManyToManyField):
                value = [i.id for i in value] if self.pk else None
            elif isinstance(f, DateTimeField):
                value = value.strftime('%Y-%m-%d %H:%M:%S') if value else None
            elif isinstance(f, DateField):
                value = value.strftime('%Y-%m-%d') if value else None
            data[f.name] = value
        return data

    def getDict(self):
        # 移除不需要的字段
        ignoreList = self.getIgnoreList()
        ignoreList = ignoreList if ignoreList else []
        fields = [
            field.name for field in self._meta.fields if field.name not in ignoreList]

        d = {}
        import datetime
        for attr in fields:
            if isinstance(getattr(self, attr), datetime.datetime):
                d[attr] = getattr(self, attr).strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(getattr(self, attr), datetime.date):
                d[attr] = getattr(self, attr).strftime('%Y-%m-%d')
            # 特殊处理datetime的数据
            elif isinstance(getattr(self, attr), BaseModel):
                d[attr] = getattr(self, attr).getDict()
            # 递归生成BaseModel类的dict
            elif self.isAttrInstance(attr, int) or self.isAttrInstance(attr, float) or self.isAttrInstance(attr, str):
                d[attr] = getattr(self, attr)

        # 由于ManyToMany类不能存在于_meta.fields，因而子类需要在getMtMFiled中返回这些字段
        mAttr = self.getMtMField()
        if mAttr is not None:
            for m in mAttr:
                if hasattr(self, m):
                    attlist = getattr(self, m).all()
                    l = []
                    for attr in attlist:
                        if isinstance(attr, BaseModel):
                            l.append(attr.getDict())
                        else:
                            dic = attr.__dict__
                            if '_state' in dic:
                                dic.pop('_state')
                            l.append(dic)
                    d[m] = l

        if 'basemodel_ptr' in d:
            d.pop('basemodel_ptr')

        return d

    def toJSON(self):
        return json.dumps(self.toDict(), ensure_ascii=False).encode('utf-8').decode()

    def getPrime(self):
        prime_list = [1, ]
        last_list = []
        for i in range(3, self+1):
            for x in range(2, i):
                last = i % x
                last_list.append(last)
                last_list.sort()
            if len(last_list) == 0 or last_list[0] != 0:
                prime_list.append(i)
            else:
                last_list.clear()
        return prime_list

    def getPackage(self):
       resultlist=[]
       newlist2 = [[self[0]]]
       newlist2bk = copy.deepcopy(newlist2)  #备份原始列表，因为有二维数组存在，不能单纯地直接copy或者用=赋予
       for i in range(1,len(self)):
           for ind in range(0,len(newlist2)):
                newlist2[ind] += self[i] #在列表元素后面直接添加新元素
                resultlist.append(newlist2[ind])  #更新后的列表，保存到结果列表中
                newlist2 = copy.deepcopy(newlist2bk) #恢复原始列表
                for ind2 in range(0,len(newlist2[ind])): #对二维元素进行更新
                    newlist2[ind][ind2] += self[i]
                    resultlist.append(newlist2[ind]) #更新后的列表，保存到结果列表中
                    newlist2 = copy.deepcopy(newlist2bk) #恢复原始列表
           newlist2 = copy.deepcopy(resultlist) #1回遍历完成后，更新原始列表，以用于下次更新
           newlist2bk = copy.deepcopy(newlist2) #同样备份一下更新后的原始列表
           if(i != len(self) -1):  #如果字符串没有遍历完，则将结果列表清空
                resultlist =[]
       resultlist2 =[]
       for xx in resultlist:  #删除重复元素,可以用unique实现
            xx.sort()   #对二维元素进行排序，否则AABBBB这种会出现重复对象
            if xx not in resultlist2:
                resultlist2.append(xx)
       return resultlist2




class Person(BaseModel):
    name = models.CharField(max_length=128)
    age = models.IntegerField()
    grade = models.IntegerField()

    def __str__(self):
        return self.name

    # def getIgnoreList(self):
    #     return ['age']


class Prime(BaseModel):
    zhishu = models.AutoField

    def __str__(self):
        return self.name


class Package(BaseModel):
    zhuhe = models.AutoField

    def __str__(self):
        return self.name


class Group(BaseModel):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):
        return self.name

    def getMtMField(self):
        return ['members']


class Membership(BaseModel):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()        # 进组时间
    invite_reason = models.CharField(max_length=64)  # 邀请原因
